package com.gxa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxa.domain.dto.EmployeeDTO;
import com.gxa.domain.entity.Employee;
import com.gxa.domain.vo.EmployeeQueryVO;
import com.gxa.domain.vo.EmployeeVO;
import com.gxa.mapper.EmployeeMapper;
import com.gxa.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

/**
 * 员工服务实现类
 */
@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
    
    @Override
    public IPage<Employee> pageQuery(EmployeeQueryVO queryVO) {
        log.info("开始分页查询员工，参数：{}", queryVO);
        
        Page<Employee> page = new Page<>(queryVO.getCurrent(), queryVO.getSize());
        log.info("分页参数：current={}, size={}", page.getCurrent(), page.getSize());
        
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        
        // 员工号查询
        if (queryVO.getEmployeeId() != null) {
            queryWrapper.eq(Employee::getEmployeeId, queryVO.getEmployeeId());
            log.info("添加员工号查询条件：{}", queryVO.getEmployeeId());
        }
        
        // 姓名模糊查询
        if (StrUtil.isNotBlank(queryVO.getName())) {
            queryWrapper.like(Employee::getName, queryVO.getName());
            log.info("添加姓名查询条件：{}", queryVO.getName());
        }
        
        // 身份证号查询
        if (StrUtil.isNotBlank(queryVO.getIdCardNo())) {
            queryWrapper.eq(Employee::getIdCardNo, queryVO.getIdCardNo());
            log.info("添加身份证号查询条件：{}", queryVO.getIdCardNo());
        }
        
        // RFID卡号查询
        if (StrUtil.isNotBlank(queryVO.getRfidCardNo())) {
            queryWrapper.eq(Employee::getRfidCardNo, queryVO.getRfidCardNo());
            log.info("添加RFID卡号查询条件：{}", queryVO.getRfidCardNo());
        }
        
        // 联系电话查询
        if (StrUtil.isNotBlank(queryVO.getPhone())) {
            queryWrapper.eq(Employee::getPhone, queryVO.getPhone());
            log.info("添加联系电话查询条件：{}", queryVO.getPhone());
        }
        
        // 在职状态查询
        if (StrUtil.isNotBlank(queryVO.getStatus())) {
            queryWrapper.eq(Employee::getStatus, queryVO.getStatus());
            log.info("添加在职状态查询条件：{}", queryVO.getStatus());
        }
        
        // 操作员等级查询
        if (queryVO.getOperatorLevel() != null) {
            queryWrapper.eq(Employee::getOperatorLevel, queryVO.getOperatorLevel());
            log.info("添加操作员等级查询条件：{}", queryVO.getOperatorLevel());
        }
        
        // 按员工号降序排列
        queryWrapper.orderByDesc(Employee::getEmployeeId);
        log.info("添加排序条件：按员工号降序");
        
        log.info("执行分页查询...");
        IPage<Employee> result = this.page(page, queryWrapper);
        
        log.info("分页查询员工完成，总记录数：{}", result.getTotal());
        log.info("分页查询员工完成，当前页记录数：{}", result.getRecords().size());
        log.info("分页查询员工完成，返回数据：{}", result.getRecords());
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addEmployee(EmployeeDTO employeeDTO) {
        log.info("开始添加员工，员工信息：{}", employeeDTO);
        
        // 暂时注释掉重复检查，方便测试
        /*
        // 检查身份证号是否已存在
        if (getEmployeeByIdCardNo(employeeDTO.getIdCardNo()) != null) {
            log.error("身份证号已存在：{}", employeeDTO.getIdCardNo());
            throw new RuntimeException("身份证号已存在");
        }
        
        // 检查RFID卡号是否已存在
        if (StrUtil.isNotBlank(employeeDTO.getRfidCardNo()) && 
            getEmployeeByRfidCardNo(employeeDTO.getRfidCardNo()) != null) {
            log.error("RFID卡号已存在：{}", employeeDTO.getRfidCardNo());
            throw new RuntimeException("RFID卡号已存在");
        }
        */
        
        Employee employee = new Employee();
        BeanUtil.copyProperties(employeeDTO, employee);
        
        // 处理照片：将base64字符串转换为byte数组
        if (StrUtil.isNotBlank(employeeDTO.getPhoto())) {
            try {
                byte[] photoBytes = java.util.Base64.getDecoder().decode(employeeDTO.getPhoto());
                employee.setPhoto(photoBytes);
            } catch (Exception e) {
                log.error("照片base64解码失败", e);
                throw new RuntimeException("照片格式错误");
            }
        }
        
        // 加密密码
        if (StrUtil.isNotBlank(employeeDTO.getPassword())) {
            employee.setPassword(BCrypt.hashpw(employeeDTO.getPassword(), BCrypt.gensalt()));
        }
        
        // 设置默认值
        if (StrUtil.isBlank(employee.getStatus())) {
            employee.setStatus("在职"); // 默认在职
        }
        if (employee.getOperatorLevel() == null) {
            employee.setOperatorLevel(1); // 默认初级
        }
        if (employee.getHireDate() == null) {
            employee.setHireDate(LocalDate.now()); // 默认入职日期为今天
        }
        
        boolean result = this.save(employee);
        log.info("添加员工完成，结果：{}", result);
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateEmployee(EmployeeDTO employeeDTO) {
        log.info("开始更新员工，员工信息：{}", employeeDTO);
        
        Employee existingEmployee = getEmployeeById(employeeDTO.getEmployeeId());
        if (existingEmployee == null) {
            log.error("员工不存在，员工号：{}", employeeDTO.getEmployeeId());
            throw new RuntimeException("员工不存在");
        }
        
        // 检查身份证号是否被其他员工使用
        Employee employeeByIdCard = getEmployeeByIdCardNo(employeeDTO.getIdCardNo());
        if (employeeByIdCard != null && !employeeByIdCard.getEmployeeId().equals(employeeDTO.getEmployeeId())) {
            log.error("身份证号已被其他员工使用：{}", employeeDTO.getIdCardNo());
            throw new RuntimeException("身份证号已被其他员工使用");
        }
        
        // 检查RFID卡号是否被其他员工使用
        if (StrUtil.isNotBlank(employeeDTO.getRfidCardNo())) {
            Employee employeeByRfid = getEmployeeByRfidCardNo(employeeDTO.getRfidCardNo());
            if (employeeByRfid != null && !employeeByRfid.getEmployeeId().equals(employeeDTO.getEmployeeId())) {
                log.error("RFID卡号已被其他员工使用：{}", employeeDTO.getRfidCardNo());
                throw new RuntimeException("RFID卡号已被其他员工使用");
            }
        }
        
        Employee employee = new Employee();
        BeanUtil.copyProperties(employeeDTO, employee);
        
        // 处理照片
        log.info("处理员工照片，员工号：{}，deletePhoto：{}，photo：{}", 
                employeeDTO.getEmployeeId(), 
                employeeDTO.getDeletePhoto(), 
                StrUtil.isNotBlank(employeeDTO.getPhoto()) ? "有新照片" : "无新照片");
        
        if (Boolean.TRUE.equals(employeeDTO.getDeletePhoto())) {
            // 如果明确要删除照片，设置为null
            log.info("删除员工照片，员工号：{}", employeeDTO.getEmployeeId());
            employee.setPhoto(null);
        } else if (StrUtil.isNotBlank(employeeDTO.getPhoto())) {
            // 如果有新照片，将base64字符串转换为byte数组
            try {
                byte[] photoBytes = java.util.Base64.getDecoder().decode(employeeDTO.getPhoto());
                employee.setPhoto(photoBytes);
                log.info("更新员工照片，员工号：{}", employeeDTO.getEmployeeId());
            } catch (Exception e) {
                log.error("照片base64解码失败", e);
                throw new RuntimeException("照片格式错误");
            }
        } else {
            // 如果没有新照片且不删除，保持原有照片
            employee.setPhoto(existingEmployee.getPhoto());
            log.info("保持原有照片，员工号：{}", employeeDTO.getEmployeeId());
        }
        
        // 如果密码不为空，则更新密码
        if (StrUtil.isNotBlank(employeeDTO.getPassword())) {
            employee.setPassword(BCrypt.hashpw(employeeDTO.getPassword(), BCrypt.gensalt()));
            log.info("更新员工密码，员工号：{}", employeeDTO.getEmployeeId());
        } else {
            // 密码为空时不更新密码，保持原有密码
            employee.setPassword(existingEmployee.getPassword());
            log.info("保持原有密码，员工号：{}", employeeDTO.getEmployeeId());
        }
        
        boolean result = this.updateById(employee);
        log.info("更新员工完成，结果：{}", result);
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteEmployee(Integer employeeId) {
        log.info("开始删除员工，员工号：{}", employeeId);
        
        Employee employee = getEmployeeById(employeeId);
        if (employee == null) {
            log.error("员工不存在，员工号：{}", employeeId);
            throw new RuntimeException("员工不存在");
        }
        
        boolean result = this.removeById(employeeId);
        log.info("删除员工完成，结果：{}", result);
        
        return result;
    }
    
    @Override
    public Employee getEmployeeById(Integer employeeId) {
        log.debug("根据员工号查询员工，员工号：{}", employeeId);
        return this.getById(employeeId);
    }
    
    @Override
    public Employee getEmployeeByIdCardNo(String idCardNo) {
        if (StrUtil.isBlank(idCardNo)) {
            return null;
        }
        
        log.debug("根据身份证号查询员工，身份证号：{}", idCardNo);
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getIdCardNo, idCardNo);
        return this.getOne(queryWrapper);
    }
    
    @Override
    public Employee getEmployeeByRfidCardNo(String rfidCardNo) {
        if (StrUtil.isBlank(rfidCardNo)) {
            return null;
        }
        
        log.debug("根据RFID卡号查询员工，RFID卡号：{}", rfidCardNo);
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getRfidCardNo, rfidCardNo);
        return this.getOne(queryWrapper);
    }
    
    @Override
    public IPage<EmployeeVO> pageQueryVO(EmployeeQueryVO queryVO) {
        log.info("开始分页查询员工VO，参数：{}", queryVO);
        
        Page<Employee> page = new Page<>(queryVO.getCurrent(), queryVO.getSize());
        log.info("分页参数：current={}, size={}", page.getCurrent(), page.getSize());
        
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        
        // 员工号查询
        if (queryVO.getEmployeeId() != null) {
            queryWrapper.eq(Employee::getEmployeeId, queryVO.getEmployeeId());
            log.info("添加员工号查询条件：{}", queryVO.getEmployeeId());
        }
        
        // 姓名模糊查询
        if (StrUtil.isNotBlank(queryVO.getName())) {
            queryWrapper.like(Employee::getName, queryVO.getName());
            log.info("添加姓名查询条件：{}", queryVO.getName());
        }
        
        // 身份证号查询
        if (StrUtil.isNotBlank(queryVO.getIdCardNo())) {
            queryWrapper.eq(Employee::getIdCardNo, queryVO.getIdCardNo());
            log.info("添加身份证号查询条件：{}", queryVO.getIdCardNo());
        }
        
        // RFID卡号查询
        if (StrUtil.isNotBlank(queryVO.getRfidCardNo())) {
            queryWrapper.eq(Employee::getRfidCardNo, queryVO.getRfidCardNo());
            log.info("添加RFID卡号查询条件：{}", queryVO.getRfidCardNo());
        }
        
        // 联系电话查询
        if (StrUtil.isNotBlank(queryVO.getPhone())) {
            queryWrapper.eq(Employee::getPhone, queryVO.getPhone());
            log.info("添加联系电话查询条件：{}", queryVO.getPhone());
        }
        
        // 在职状态查询
        if (StrUtil.isNotBlank(queryVO.getStatus())) {
            queryWrapper.eq(Employee::getStatus, queryVO.getStatus());
            log.info("添加在职状态查询条件：{}", queryVO.getStatus());
        }
        
        // 操作员等级查询
        if (queryVO.getOperatorLevel() != null) {
            queryWrapper.eq(Employee::getOperatorLevel, queryVO.getOperatorLevel());
            log.info("添加操作员等级查询条件：{}", queryVO.getOperatorLevel());
        }
        
        // 按员工号降序排列
        queryWrapper.orderByDesc(Employee::getEmployeeId);
        log.info("添加排序条件：按员工号降序");
        
        log.info("执行分页查询...");
        IPage<Employee> employeePage = this.page(page, queryWrapper);
        
        // 转换为EmployeeVO
        Page<EmployeeVO> voPage = new Page<>(employeePage.getCurrent(), employeePage.getSize(), employeePage.getTotal());
        voPage.setRecords(employeePage.getRecords().stream().map(this::convertToVO).collect(java.util.stream.Collectors.toList()));
        
        log.info("分页查询员工VO完成，总记录数：{}", voPage.getTotal());
        log.info("分页查询员工VO完成，当前页记录数：{}", voPage.getRecords().size());
        
        return voPage;
    }
    
    @Override
    public EmployeeVO getEmployeeVOById(Integer employeeId) {
        log.debug("根据员工号查询员工VO，员工号：{}", employeeId);
        Employee employee = this.getById(employeeId);
        if (employee == null) {
            return null;
        }
        return convertToVO(employee);
    }
    
    /**
     * 将Employee实体转换为EmployeeVO
     */
    private EmployeeVO convertToVO(Employee employee) {
        EmployeeVO vo = new EmployeeVO();
        BeanUtil.copyProperties(employee, vo);
        
        // 转换照片为base64字符串
        if (employee.getPhoto() != null && employee.getPhoto().length > 0) {
            vo.setPhoto(java.util.Base64.getEncoder().encodeToString(employee.getPhoto()));
        }
        
        // 设置密码（用于查看）
        vo.setPassword(employee.getPassword());
        
        log.debug("转换员工VO，员工号：{}，密码字段：{}，密码长度：{}", 
                employee.getEmployeeId(), 
                employee.getPassword() != null ? "有密码" : "无密码",
                employee.getPassword() != null ? employee.getPassword().length() : 0);
        
        return vo;
    }
    
    @Override
    public Employee findByUsernameOrCardNo(String username) {
        log.info("根据用户名或卡号查找员工，用户名：{}", username);
        
        if (StrUtil.isBlank(username)) {
            return null;
        }
        
        // 先尝试按员工号查找
        try {
            Integer employeeId = Integer.parseInt(username);
            Employee employee = this.getById(employeeId);
            if (employee != null) {
                log.info("按员工号找到员工：{}", employee);
                return employee;
            }
        } catch (NumberFormatException e) {
            log.debug("用户名不是数字格式，尝试按RFID卡号查找");
        }
        
        // 再尝试按RFID卡号查找
        Employee employee = getEmployeeByRfidCardNo(username);
        if (employee != null) {
            log.info("按RFID卡号找到员工：{}", employee);
            return employee;
        }
        
        log.info("未找到匹配的员工");
        return null;
    }
    
    @Override
    public boolean verifyPassword(String inputPassword, String storedPassword) {
        log.info("验证密码");
        
        if (StrUtil.isBlank(inputPassword) || StrUtil.isBlank(storedPassword)) {
            log.warn("密码为空，验证失败");
            return false;
        }
        
        // 首先尝试直接比较（支持明文密码）
        if (inputPassword.equals(storedPassword)) {
            log.info("明文密码验证成功");
            return true;
        }
        
        // 如果直接比较失败，尝试BCrypt验证（支持加密密码）
        try {
            boolean isValid = BCrypt.checkpw(inputPassword, storedPassword);
            log.info("BCrypt密码验证结果：{}", isValid);
            return isValid;
        } catch (Exception e) {
            log.error("BCrypt密码验证异常", e);
            return false;
        }
    }
    
    @Override
    public Integer getIdByName(String name) {
        log.info("根据员工姓名查询员工ID，姓名：{}", name);
        
        if (StrUtil.isBlank(name)) {
            log.warn("员工姓名为空");
            return null;
        }
        
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getName, name);
        Employee employee = this.getOne(queryWrapper);
        
        if (employee != null) {
            log.info("找到员工，姓名：{}，员工ID：{}", name, employee.getEmployeeId());
            return employee.getEmployeeId();
        } else {
            log.warn("未找到员工，姓名：{}", name);
            return null;
        }
    }
} 